<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
    </head>
    <body>
        <script>
            // 手写实现Object.create()方法
            function myCreate(obj) {
                let F = function () {};
                F.prototype = obj;
                return new F();
            }
            // 手写实现instance方法
            function myInstanceOf(left, right) {
                let proto = left.getProtoTypeOf(left);
                let prototype = right.prototype;
                while (true) {
                    if (proto == null) {
                        return false;
                    }

                    if (props == prototype) {
                        return true;
                    }
                    proto = proto.getProtoTypeOf(proto);
                }
            }
            // new操作符
            function myNew(Fn, ...args) {
                let obj = {};
                obj.__proto__ = Fn.prototype;
                let result = Fn.call(...args);
                return result instanceof Object ? result : obj;
            }
            // 手写call
            function myCall(context) {
                if (typeof this != 'function') {
                    throw new Error('error');
                }
                context = context || window;
                let args = [...arguments].slice(1);
                context.Fn = this;
                let result = context.Fn(...args);
                delete context.Fn;
                return result;
            }
            // 手写bind
            function myBind() {
                if (typeof this != 'function') {
                    throw new Error('error');
                }
                context = context || window;
                let args = [...arguments].slice(1);
                context.Fn = this;
                let result = context.Fn(args);
                delete context.Fn;
                return result;
            }
            // 手写实现防抖函数
            function debounce(fn, delay) {
                let timer;
                return function (...args) {
                    if (timer) clearTimeout(timer);
                    timer = setTimeout(() => {
                        fn.apply(null, args);
                    }, delay);
                };
            }
            function debounce1(fn, delay, immediate) {
                let timer;
                return function (...args) {
                    if (immediate) {
                        // 第一次点击立即执行
                        let fastRun = !timer;
                        timer = setTimeout(() => {
                            timer = null;
                        }, delay);
                        fn.apply(this, args);
                    } else {
                        // 第一次点击不会立即执行
                        if (timer) clearTimeout(timer);
                        timer = setTimeout(() => {
                            fn.apply(fn, args);
                        }, delay);
                    }
                };
            }
            // 手写节流函数
            function throller(fn, delay) {
                let timer = null;
                return function (...args) {
                    if (!timer) {
                        timer = setTimeout(() => {
                            fn.apply(this, args);
                            timer = null;
                        }, delay);
                    }
                };
            }
            function throller2(fn, delay) {
                let oldTime = Date.now();
                return function (...args) {
                    let newTime = Date.now();
                    if (newTime - oldTime > delay) {
                        fn.apply(this, args);
                        oldTime = Date.now();
                    }
                };
            }
            // 手写类型判断函数
            function myTypeOf(obj) {
                let type = typeof obj;
                if (type !== 'object') {
                    return type;
                }
                return Object.prototype.toString.call(obj).slice(8, -1).toLowerCase();
            }
        </script>
    </body>
</html>
